﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Surface.Presentation.Controls;
using MTBrainStorm.Framework;
using MTBrainStorm.Framework.Messaging;

namespace MTBrainStorm.ViewModels
{
    public class MainWindowViewModel
    {
        public ObservableCollection<MultiTouchElementViewModel> Elements { get; set; }

        public ObservableCollection<JointViewModel> Joints { get; set; }

        public MultiTouchElementViewModel Element { get; set; }

        public MainWindowViewModel()
        {
            Elements = new ObservableCollection<MultiTouchElementViewModel>();

            Joints = new ObservableCollection<JointViewModel>();

            Messenger.Default.Register(this, new Action<KeyValuePair<string, TextElementViewModel>>(ShowKbd));
        }

        private void ShowKbd(KeyValuePair<string, TextElementViewModel> obj)
        {
            if (obj.Key == "show")
            { 
                Elements.Add(obj.Value.AttachedKeyboard);
                Joints.Add(new JointViewModel {StartElement = obj.Value, EndElement = obj.Value.AttachedKeyboard});
            }
            else
            {
                Elements.Remove(obj.Value.AttachedKeyboard);
                foreach (var joint in Joints)
                {
                    if (joint.StartElement == obj.Value && joint.EndElement == obj.Value.AttachedKeyboard)
                    {
                        Joints.Remove(joint);
                        break;
                    }
                }
            }
        }


        private RelayCommand<ContainerManipulationCompletedEventArgs> _joinOrUnjointIfPossible;
        public ICommand JoinOrUnjoinIfPossible
        {
            get
            {
                return _joinOrUnjointIfPossible ??
                    (_joinOrUnjointIfPossible = 
                    new RelayCommand<ContainerManipulationCompletedEventArgs>(ExecuteJoinOrUnjoinIfPossible));
            }
        }

        private void ExecuteJoinOrUnjoinIfPossible(ContainerManipulationCompletedEventArgs e)
        {
            var fe = (FrameworkElement) e.OriginalSource;
            if(typeof(IDocumentElementViewModel).IsAssignableFrom(fe.DataContext.GetType()))
            {
                var source = ((MultiTouchElementViewModel)fe.DataContext);
                foreach (var element in Elements)
                {
                    if (element != source && typeof(IDocumentElementViewModel).IsAssignableFrom(element.GetType()))
                    {
                        var sourceRect = new Rect(
                            source.Position.X,
                            source.Position.Y,
                            50,
                            50);

                        var elementRect = new Rect(
                            element.Position.X,
                            element.Position.Y,
                            50,
                            50);

                        if (sourceRect.IntersectsWith(elementRect))
                        {
                            JointViewModel j = null;
                            foreach (var joint in Joints)
                            {
                                if ((joint.StartElement == source && joint.EndElement == element)
                                    || (joint.StartElement == element && joint.EndElement == source))
                                {
                                    j = joint;
                                }
                            }

                            if (j != null)
                                Joints.Remove(j);
                            else
                                Joints.Add(new JointViewModel {StartElement = source, EndElement = element});
                        }
                    }
                }
            }
        }

        private RelayCommand<MultiTouchElementViewModel> _removeNode;
        public ICommand RemoveNode
        {
            get { return _removeNode ?? (_removeNode = new RelayCommand<MultiTouchElementViewModel>(ExecuteRemoveNode)); }
        }

        private void ExecuteRemoveNode(MultiTouchElementViewModel obj)
        {
            if (typeof(IDocumentElementViewModel).IsAssignableFrom(obj.GetType()))
            {
                Elements.Remove(obj);
                var jointsToRemove = new List<JointViewModel>();
                foreach (var joint in Joints)
                {
                    if (joint.StartElement == obj || joint.EndElement == obj)
                        jointsToRemove.Add(joint);
                }

                foreach (var joint in jointsToRemove)
                {
                    Joints.Remove(joint);
                }
            }
        }

        private RelayCommand<string> _addElement;
        public ICommand AddElement
        {
            get { return _addElement ?? (_addElement = new RelayCommand<string>(ExecuteAddElement)); }
        }

        private void ExecuteAddElement(string s)
        {
            var r = new Random(DateTime.Now.Millisecond);
            var position = 
                new Point(
                    r.Next((int)SystemParameters.PrimaryScreenWidth), 
                    r.Next((int)SystemParameters.PrimaryScreenHeight)
                    );
            var rotation = r.Next(360);

            MultiTouchElementViewModel element;
            if (s == "text")
            {
                element = new TextElementViewModel();
                element.Width = 200;
                element.Height = 50;
            }
            else
            {
                element = new TouchInkCanvasViewModel();
                element.Width = 200;
                element.Height = 200;
                
                ((TouchInkCanvasViewModel) element).CanDraw = false;
            }
            element.Position = position;
            element.Rotation = rotation;
            element.ScaleX = 1;
            element.ScaleY = 1;

            Elements.Add(element);
        }
    }
}
